#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <cuda_runtime.h>

__global__ void add (int a, int b, int *c) {
	*c = a+b;
}

__global__ void vector_add(int*a, int*b, int*c) {
	int idx = blockIdx.x % 1000000 * blockDim.x + threadIdx.x;
	if(idx < 1000){
		c[idx] = a[idx] + b[idx];	
	}
}

int main (int argc, char* argv[]) {
	printf("Hello from your GPU!\n");
	const int N = 1000;
	const int ITERATIONS = 1000000;


	const int BLOCK_SIZE = 256;
	int BLOCKS;

	int a[N], b[N], c[N], cpu_c[N];
	int *dev_a, *dev_b, *dev_c;

	//initializing a and b vectors
	for (int i=0; i<N; i++){
		a[i] = i;
		b[i] = i % 73;
	}


	BLOCKS = (ITERATIONS * N)/BLOCK_SIZE + (((ITERATIONS * N)%BLOCK_SIZE == 0)? 0 : 1);
	
	
	cudaMalloc<int>(&dev_a, sizeof(int)*N);
	cudaMalloc<int>(&dev_b, sizeof(int)*N);
	cudaMalloc<int>(&dev_c, sizeof(int)*N);

	cudaMemcpy(dev_a, a, sizeof(int)*N, cudaMemcpyKind::cudaMemcpyHostToDevice);
	cudaMemcpy(dev_b, b, sizeof(int)*N, cudaMemcpyKind::cudaMemcpyHostToDevice);
	clock_t start = clock();
	vector_add<<<BLOCKS, BLOCK_SIZE>>>(dev_a, dev_b, dev_c);
	clock_t end = clock();
	cudaMemcpy(c, dev_c, sizeof(int)*N, cudaMemcpyDeviceToHost);
	

	clock_t cpu_start = clock();
	for(int j = 0; j < ITERATIONS; j++){ 
		for (int i=0; i<N; i++) {
			cpu_c[i] = a[i] + b[i];
		}
	}
	clock_t cpu_end = clock();
	
	printf("performing %d additions:\n", N*ITERATIONS);
	printf("GPU time: %d ms\n", (end - start));
	printf("processor time: %d ms\n", (cpu_end - cpu_start));
	cudaFree(dev_c);

	getchar();
	return EXIT_SUCCESS;

}